package org.tis.tools.senior.module.developer.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.tis.tools.core.utils.StringUtil;
import org.tis.tools.senior.module.developer.controller.request.AgainDeliveryRequest;
import org.tis.tools.senior.module.developer.controller.request.RepealAddRequest;
import org.tis.tools.senior.module.developer.dao.SRepealMapper;
import org.tis.tools.senior.module.developer.entity.*;
import org.tis.tools.senior.module.developer.entity.enums.*;
import org.tis.tools.senior.module.developer.entity.vo.DeliveryProjectDetail;
import org.tis.tools.senior.module.developer.entity.vo.RepealDetail;
import org.tis.tools.senior.module.developer.entity.vo.SProfileDetail;
import org.tis.tools.senior.module.developer.exception.DeveloperException;
import org.tis.tools.senior.module.developer.service.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * sRepeal的Service接口实现类
 * 
 * @author Auto Generate Tools
 * @date 2018/09/26
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SRepealServiceImpl extends ServiceImpl<SRepealMapper, SRepeal> implements ISRepealService {

    @Autowired
    private ISWorkitemService workitemService;

    @Autowired
    private ISDeliveryService deliveryService;

    @Autowired
    private ISDeliveryListService deliveryListService;

    @Autowired
    private ISRollbackService rollbackService;

    @Autowired
    private ISStandardListService standardListService;

    @Autowired
    private ISRepealListService repealListService;

    @Autowired
    private ISProfilesService profilesService;

    @Autowired
    private ISCheckService checkService;

    @Autowired
    private ISProjectService projectService;

    @Override
    public SProfileDetail selectPackTime(Integer guidRepeal) throws ParseException {
        SRepeal repeal = selectById(guidRepeal);
        if (repeal == null){
            throw new DeveloperException("此延期申请不存在！");
        }
        return deliveryService.profileDeteilVerify(repeal.getGuidProfiles());
    }

    @Override
    public void addRepealApply(String userId, RepealAddRequest request) {
        SWorkitem workitem = workitemService.selectById(request.getGuidWorkitem());
        if(workitem == null){
            throw new DeveloperException("对应工作项信息不存在！");
        }
        SProfiles profiles = profilesService.selectById(request.getGuidProfiles());
        if (profiles == null){
            throw new DeveloperException("对应运行环境信息不存在！");
        }
        if (profiles.getIsRepeal().equals("false")){
            throw new DeveloperException("投放的运行环境未开启可投放延期申请！");
        }

        EntityWrapper<SRepeal> repealEntityWrapper = new EntityWrapper<>();
        repealEntityWrapper.eq(SRepeal.COLUMN_GUID_WORKITEM, request.getGuidWorkitem());
        repealEntityWrapper.eq(SRepeal.COLUMN_REPEAL_STATUS, RepealStatus.MODIFIED);
        List<SRepeal> repeals = selectList(repealEntityWrapper);
        if (repeals.size() > 0){
            throw new DeveloperException("此工作项已有延期投产申请未处理完成，请处理完成后再回退！");
        }

        List<String> deilveryResults = new ArrayList<>();
        deilveryResults.add(DeliveryResult.FAILED.getValue().toString());
        deilveryResults.add(DeliveryResult.DELIVERED.getValue().toString());
        EntityWrapper<SDelivery> deliveryEntityWrapper = new EntityWrapper<>();
        deliveryEntityWrapper.eq(SDelivery.COLUMN_GUID_WORKITEM, request.getGuidWorkitem());
        deliveryEntityWrapper.notIn(SDelivery.COLUMN_DELIVERY_RESULT, deilveryResults);
        List<SDelivery> deliveries = deliveryService.selectList(deliveryEntityWrapper);
        if (deliveries.size() > 0){
            throw new DeveloperException("此工作项有投放申请在申请中或正在处理中，不允许生成延期投产申请！");
        }

        EntityWrapper<SRollback> rollbackEntityWrapper = new EntityWrapper<>();
        rollbackEntityWrapper.eq(SRollback.COLUMN_GUID_WORKITEM, request.getGuidWorkitem());
        rollbackEntityWrapper.eq(SRollback.COLUMN_ROLLBACK_STATUS, RollbackStatus.UNDERWAY);
        List<SRollback> rollbacks = rollbackService.selectList(rollbackEntityWrapper);
        if (rollbacks.size() > 0){
            throw new DeveloperException("此工作项已有回退申请正在回退中，请完成后再操作！");
        }

        List<SStandardList> standardLists = standardListService.selectBatchIds(request.getGuidStandarLists());
        if (standardLists.size() != request.getGuidStandarLists().size()){
            throw new DeveloperException("未选择正确的标准清单代码或有代码已被回退，请重新操作！");
        }

        SRepeal repeal = new SRepeal();
        repeal.setGuidWorkitem(request.getGuidWorkitem());
        repeal.setGuidProfiles(request.getGuidProfiles());
        repeal.setApplyPerson(userId);
        repeal.setRepealDesc(request.getRepealDesc());
        repeal.setRepealTime(new Date());
        repeal.setRepealStatus(RepealStatus.MODIFIED);
        //新增延期投产申请
        insert(repeal);

        List<SRepealList> repealLists = new ArrayList<>();
        for (SStandardList standardList:standardLists){
            SRepealList repealList = new SRepealList();
            BeanUtils.copyProperties(standardList, repealList);
            repealList.setGuid(null);
            repealList.setGuidRepeal(repeal.getGuid());
            repealList.setDeliveryStatus(DeliveryStatus.NOTLAUNCH);
            if(repealList.getCommitType().getValue().equals(CommitType.ADDED.getValue())){
                repealList.setCommitType(CommitType.MODIFIED);
            }
            repealLists.add(repealList);
        }
        repealListService.insertBatch(repealLists);
    }

    @Override
    public Page<RepealDetail> selectRepealAll(Page<RepealDetail> page, EntityWrapper<RepealDetail> wrapper) {

        return page.setRecords(this.baseMapper.selectRepealAll(page, wrapper));
    }

    @Override
    public void affirmRepealSeccess(String userId, Integer guidRepeal) {
        SRepeal repeal = selectById(guidRepeal);
        if (repeal == null){
            throw new DeveloperException("此延期申请不存在！");
        }
        if (repeal.getRepealStatus().equals(RepealStatus.DELETED)){
            throw new DeveloperException("此延期申请已经成功撤销！");
        }
        repeal.setRepealStatus(RepealStatus.DELETED);
        repeal.setDisposePerson(userId);
        updateById(repeal);
    }

    @Override
    public void deleteRepeal(Integer guidRepeal) {
        SRepeal repeal = selectById(guidRepeal);
        if (repeal == null){
            throw new DeveloperException("对应延期投产信息不存在！");
        }
        if (repeal.getRepealStatus().equals(RepealStatus.DELETED)){
            throw new DeveloperException("此延期申请已完成延期，不允许删除！");
        }
        EntityWrapper<SRepealList> repealListEntityWrapper = new EntityWrapper<>();
        repealListEntityWrapper.eq(SRepealList.COLUMN_GUID_REPEAL, repeal.getGuid());
        List<SRepealList> repealLists = repealListService.selectList(repealListEntityWrapper);
        //删除此延期申请的所有代码
        repealListService.deleteBatchIds(repealLists.stream().map(SRepealList::getGuid).collect(Collectors.toList()));
        //删除延期申请
        deleteById(repeal.getGuid());
    }

    @Override
    public Page<SRepealList> selectRepealListDetail(Integer guidRepeal,
                                                    Page<SRepealList> page, EntityWrapper<SRepealList> wrapper) {
        wrapper.eq(SRepealList.COLUMN_GUID_REPEAL, guidRepeal);
        wrapper.eq(SRepealList.COLUMN_DELIVERY_STATUS, DeliveryStatus.NOTLAUNCH);
        Page<SRepealList> repealListPage = repealListService.selectPage(page, wrapper);
        return repealListPage;
    }

    @Override
    public void againDelivery(String userId, AgainDeliveryRequest request) throws ParseException {
        SRepeal repeal = selectById(request.getGuidRepeal());
        if (repeal == null){
            throw new DeveloperException("对应延期投产申请guid为"+repeal.getGuid()+"信息不存在！");
        }
        List<SRepealList> repealLists = repealListService.selectBatchIds(request.getGuidRepealLists());
        if (repealLists.size() != request.getGuidRepealLists().size()){
            throw new DeveloperException("有找不到对应得延期投产代码信息！");
        }
        SProfiles profiles = profilesService.selectById(repeal.getGuidProfiles());
        if(profiles == null){
            throw new DeveloperException("找不到延期投产申请的运行环境guid为"+ repeal.getGuid()+ "，或者已被删除！");
        }
        if (profiles.getIsAllowDelivery().getValue().equals(IsAllowDelivery.NOTALLOW.getValue())){
            throw new DeveloperException("再次投放的运行环境已被关闭，不允许投放");
        }

        //判断投放时间及投放窗口是否合理
        Date date = new Date();
        SimpleDateFormat ymdFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat hmFormat = new SimpleDateFormat("HH:mm");
        if (ymdFormat.format(request.getDeliveryTime()).equals(ymdFormat.format(date))){
            //投放窗口的时间戳
            long time1 = hmFormat.parse(request.getPackTiming()).getTime();
            //当前时间的时间戳
            long time2 = hmFormat.parse(hmFormat.format(date)).getTime();
            if(time2 > time1){
                throw new DeveloperException("你投放的窗口已经过期，请选择下一个窗口投放！");
            }
        }else{
            //将投放时间转成时间戳
            long deliverTime1 = ymdFormat.parse(ymdFormat.format(request.getDeliveryTime())).getTime();
            //当前时间的时间戳
            long time2 = ymdFormat.parse(ymdFormat.format(request.getDeliveryTime())).getTime();
            if(time2 > deliverTime1){
                throw new DeveloperException("你选择的投放日期已是过去日期，请重新投放时间！");
            }
        }

        //集合添加核对中及核对成功状态，控制投放申请的环境是否可投放
        List<CheckStatus> checkStatuses = new ArrayList<>();
        checkStatuses.add(CheckStatus.WAIT);
        checkStatuses.add(CheckStatus.SUCCESS);
        //获取这个投放申请的运行环境是否有正在核对中
        EntityWrapper<SCheck> checkEntityWrapper = new EntityWrapper<>();
        checkEntityWrapper.eq(SCheck.COLUMN_GUID_PROFILES, repeal.getGuidProfiles())
            .in(SCheck.COLUMN_CHECK_STATUS, checkStatuses)
            .eq(SCheck.COLUMN_PACK_TIMING, request.getPackTiming())
            .eq("DATE_FORMAT(" + SCheck.COLUMN_DELIVERY_TIME + ", '%Y-%m-%d')",
                    new SimpleDateFormat("yyyy-MM-dd").format(request.getDeliveryTime()));

        if(checkService.selectList(checkEntityWrapper).size() > 0){
            throw new DeveloperException("你本次投放的环境窗口有申请正在核对中或已核对完成，请投放下一个窗口！");
        }

        //获取投放日期以及具体打包窗口是否已经完成投放
        EntityWrapper<SDelivery> deliveryWrapper = new EntityWrapper<>();
            deliveryWrapper.in(SDelivery.COLUMN_DELIVERY_RESULT,DeliveryResult.doneResult())
            .eq("DATE_FORMAT(" + SDelivery.COLUMN_DELIVERY_TIME + ", '%Y-%m-%d')",
                    new SimpleDateFormat("yyyy-MM-dd").format(request.getDeliveryTime()))
            .eq(SDelivery.COLUMN_PACK_TIMING,request.getPackTiming())
            .eq(SDelivery.COLUMN_GUID_PROFILES,repeal.getGuidProfiles());

        List<SDelivery> deliveries = deliveryService.selectList(deliveryWrapper);
        if(deliveries.size() > 0){
            throw new DeveloperException("你选择的投放环境对应的打包窗口已完成投放，请选择其他时间投放！");
        }

        SDelivery delivery = new SDelivery();
        delivery.setApplyAlias("延期投产");
        delivery.setGuidWorkitem(repeal.getGuidWorkitem());
        delivery.setGuidProfiles(repeal.getGuidProfiles());
        delivery.setDeliveryType(DeliveryType.REPEAL);
        delivery.setProposer(userId);
        delivery.setApplyTime(new Date());
        delivery.setPackTiming(request.getPackTiming());
        delivery.setDeliveryTime(request.getDeliveryTime());
        delivery.setDeliveryResult(DeliveryResult.APPLYING);
        delivery.setBatchNumber(String.valueOf(System.currentTimeMillis()));
        delivery.setApplyType(ApplyType.SREPEAL);
        delivery.setBeginVersion(0);
        delivery.setEndVersion(0);
        //新增投放申请
        deliveryService.insert(delivery);

        List<SDeliveryList> deliveryLists = new ArrayList<>();
        for (SRepealList repealList:repealLists){
            SDeliveryList deliveryList = new SDeliveryList();
            BeanUtils.copyProperties(repealList, deliveryList);
            deliveryList.setGuid(null);
            deliveryList.setGuidDelivery(delivery.getGuid());
            deliveryList.setFromType(DeliveryListFromType.REPEAL);
            deliveryLists.add(deliveryList);
        }
        deliveryListService.insertBatch(deliveryLists);

        for (SRepealList repealList:repealLists){
            repealList.setDeliveryStatus(DeliveryStatus.LAUNCH);
        }
        repealListService.updateBatchById(repealLists);
        if (StringUtil.isBlank(repeal.getGuidDelivery())){
            repeal.setGuidDelivery(delivery.getGuid().toString());
        }else{
            repeal.setGuidDelivery( repeal.getGuidDelivery() +","+ delivery.getGuid());
        }
       updateById(repeal);
    }

    @Override
    public List<DeliveryProjectDetail> selectRepealListDetail(Integer guidRepeal) {
        SRepeal repeal = selectById(guidRepeal);
        if (repeal == null){
            throw new DeveloperException("此延迟投产申请不存在或已被删除！");
        }
        EntityWrapper<SRepealList> repealListEntityWrapper = new EntityWrapper<>();
        repealListEntityWrapper.eq(SRepealList.COLUMN_GUID_REPEAL, guidRepeal);
        List<SRepealList> repealLists  = repealListService.selectList(repealListEntityWrapper);

        return DeliveryProjectDetail.getRepealDetail(repealLists, projectService.selectList(null));
    }


}

